use std::collections::VecDeque;
use std::thread;
use std::thread::JoinHandle;
use std::time::Duration;

use anyhow::{anyhow, bail};
use log::{debug, error, info};

use crate::{config, msghandler};
use crate::common::CommResult;
use crate::config::{exist_hid_file, get_hclient, get_hid, get_hid_filepath};
use crate::dto::base_dto::ResDto;
use crate::dto::biz_code;
use crate::dto::task::{BatchTaskInfo, BizTask};
use crate::logger;
use crate::msghandler::{post_common, post_common_rt};
use crate::provider::host_provider;
use crate::provider::host_provider::{get_host, get_ip, get_mac_addr};
use crate::run::task_pool;
use crate::run::task_pool::TaskPool;

/// 启动agent
///
/// ```
/// 1.初始化配置
/// 2.注册主机
/// 5.loop阻塞线程,处理任务
/// 5.1 心跳获取任务处理
/// ```
pub fn start() -> CommResult<()> {
    // 初始化配置文件,包含日志，全局httpclient
    init_all_config()?;
    // 加载系统信息为全局变量
    host_provider::init();
    config::load_hid()?;
    //打印启动信息
    print_agent_info();
    //注册主机,只有没有hid的时候才是第一次安装
    reg_host()?;
    //加载hid为全局变量
    update_host_info()?;
    //死循环，等待服务端下发任务
    block_handle();
    Ok(())
}

fn update_host_info() -> CommResult<ResDto> {
    post_common_rt("".to_string(), biz_code::HOST_INFO, &get_host())
}

fn print_agent_info() {
    let mut info = String::new();
    info.push_str(fmt_tab("HOST_ID", get_hid()).as_str());
    info.push_str(fmt_tab("IP", get_ip()).as_str());
    info.push_str(fmt_tab("MAC", get_mac_addr()).as_str());
    info.push_str(fmt_tab("CONFIG_PATH", config::get_path()).as_str());
    info.push_str(fmt_tab("LOG_PATH", config::get_log_dir()).as_str());
    info!("agent开始启动 \n{}",info)
}

fn fmt_tab<T: std::fmt::Display>(s: &str, t: T) -> String {
    format!("\t{:<12}: {}\n", s, t)
}

/// 初始化配置文件，日志输出
fn init_all_config() -> CommResult<()> {
    let cfpath = "config/config.yml".to_string();
    config::init(cfpath)?;
    logger::init(config::get_log_dir(), config::get_log_level())
}

fn reg_host() -> CommResult<()> {
    if !exist_hid_file() {
        let cdto = host_provider::get_host();
        let hid = msghandler::reg_host(cdto)?;
        if hid.is_empty() {
            bail!("服务端获取hid为空");
        }
        let path = get_hid_filepath();
        config::save_hid(path, hid.clone())?;
        config::load_hid()?;
        info!("主机注册成功>HOST_ID:{}",hid);
    }
    Ok(())
}


/// 心跳等待服务端下发任务
fn block_handle() {
    info!("开启心跳获取任务");
    //心跳时间，3秒一次
    let mut hb_sleep = 3;
    let mut task_poll = task_pool::TaskPool::new();
    loop {
        //3秒心跳一次
        if hb_sleep >= 3 {
            hb_sleep = 0;
            if let Err(e) = run_heartbeat(&mut task_poll) {
                error!("心跳返回错误->{}",e)
            }
        }
        thread::sleep(Duration::from_secs(1));
        hb_sleep += 1;
    }
}

fn run_heartbeat(task_pool: &mut TaskPool) -> CommResult<()> {
    let bti = msghandler::fetch_msg_task();
    task_pool.add(bti);
    task_pool.run();
    Ok(())
}